package com.dhcc.core.framework.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class SerialybUtils {
	private static final String key = "bc5245fcdda94995";
	private static String fileName = "encrypt.ini";

	private static Map<String, Object> authorizationType = new HashMap();
	private static Integer enNum;

	public static void main(String[] args) {
		try {
			String serverCode = getSerialybMachineCode();
			System.err.println("机器码："+serverCode);//N0MtOEEtRTEtNjctMUYtNkMmQkZFQkZCRkYwMDA4MDZDMQ==

//			String string = "iMedical^V1.0^BPV^2022-08-26^软件许可授权使用单位^1^N0MtOEEtRTEtNjUtRUQtMEUmQkZFQkZCRkYwMDA4MDZDMQ==";
//			String s1 = serialybEncodeGeneral(string);
//			System.out.println(s1);
//
//			String s2 = serialybDecode(s1);
//			System.out.println(s2);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void writeToFile(String string) {
		try {
			File file = new File(fileName);

			if (!file.exists()) {
				file.createNewFile();
			}

			FileOutputStream fos = new FileOutputStream(file, false);

			fos.write(new StringBuilder().append("\r\n").append(AESUtils.encryptByAES(string, "bc5245fcdda94995"))
					.toString().getBytes(StandardCharsets.UTF_8));

			fos.flush();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static List<String> readToFile() {
		List list = new ArrayList();
		try {
			try {
				File file = new File(fileName);

				if (!file.exists()) {
					file.createNewFile();
				}

				BufferedReader br = new BufferedReader(new FileReader(fileName));
				String s;
				while ((s = br.readLine()) != null) {
					list.add(AESUtils.decryptByAES(s, "bc5245fcdda94995"));
				}
				br.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	public static String serialybEncode(String str) {
		StringBuffer stringBuffer = new StringBuffer();
		String[] strings = str.split("\\^");

		String machineCodeStr = strings[6];
		String[] machineCodes = machineCodeStr.split(",");
		if ((machineCodes != null) && (machineCodes.length > 0)) {
			for (int i = 0; i < machineCodes.length; i++) {
				String machineCode = machineCodes[i];
				StringBuffer base64Str = new StringBuffer();
				base64Str.append(strings[0]);
				base64Str.append("^");
				base64Str.append(strings[1]);
				base64Str.append("^");
				base64Str.append(strings[2]);
				base64Str.append("^");
				base64Str.append(strings[3]);
				base64Str.append("^");
				base64Str.append(strings[4]);
				base64Str.append("^");
				base64Str.append(strings[5]);
				base64Str.append("^");
				base64Str.append(machineCode);
				String base64String = base64Str.toString();
				for (int j = 0; j < enNum.intValue(); j++) {
					base64String = base64Encode(base64String);
				}
				stringBuffer.append(base64String);
				if (i != machineCodes.length - 1) {
					stringBuffer.append("#");
				}
			}
		}
		return stringBuffer.toString();
	}

	public static String serialybEncodeGeneral(String str) {
		String enSerialNumber = str;
		for (int j = 0; j < enNum.intValue(); j++) {
			enSerialNumber = base64Encode(enSerialNumber);
		}
		return enSerialNumber;
	}

	public static String serialybDecode(String str) {
		String enSerialNumber = str;
		for (int j = 0; j < enNum.intValue(); j++) {
			enSerialNumber = base64Decode(enSerialNumber);
		}
		return enSerialNumber;
	}

	public static String getSerialybMachineCode() {
		StringBuffer str = new StringBuffer();
		String serialybMachineCode;
		try {
			String macAddress = getMacAddress();
			if (("-1".equals(macAddress)) || ("-2".equals(macAddress))) {
				serialybMachineCode = macAddress;
			} else {
				str.append(macAddress);
				str.append("&");
				str.append(getCpuId());
				serialybMachineCode = base64Encode(str.toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
			serialybMachineCode = "-2";
		}
		return serialybMachineCode;
	}

	public static Integer checkSerialNumber(List<String> serialNumberList) {
		Integer num = Integer.valueOf(-2);

		Long hisoryTime = null;
		String hisoryFlag = null;
		String hisoryLic = null;
		try {
			List historyList = readToFile();
			if ((historyList != null) && (historyList.size() > 0)) {
				String hisory = (String) historyList.get(historyList.size() - 1);
				String[] hisorys = hisory.split("#");
				hisoryTime = Long.valueOf(hisorys.length > 0 ? hisorys[0] : "");
				hisoryFlag = hisorys.length > 1 ? hisorys[1] : "";
			}

			String writeLic = "";
			if ((serialNumberList != null) && (serialNumberList.size() > 0))
				for (int i = 0; i < serialNumberList.size(); i++) {
					String serialNumber = (String) serialNumberList.get(i);
					if ((serialNumber != null) && (serialNumber != "") && (serialNumber.length() > 0)) {
						String enSerialNumber = serialNumber;
						for (int j = 0; j < enNum.intValue(); j++) {
							enSerialNumber = base64Decode(enSerialNumber);
						}

						String[] serialNumbers = enSerialNumber.split("\\^");
						if (serialNumbers.length == 7) {
							String machineCode = getSerialybMachineCode();

							String serialMachineCode = serialNumbers[6];

							String serialEndTime = serialNumbers[3];
							if ((serialMachineCode != null) && (serialMachineCode.length() > 0)
									&& (serialEndTime != null) && (serialEndTime.length() > 0)) {
								if (machineCode.equals(serialMachineCode)) {
									SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
									try {
										Date date = simpleDateFormat.parse(serialEndTime);
										String currentDate = simpleDateFormat.format(new Date());
										Date currentDay = simpleDateFormat.parse(currentDate);
										Long currentMillis = Long.valueOf(currentDay.getTime());
										Long dateMillis = Long.valueOf(date.getTime());
										long time = dateMillis.longValue() - currentMillis.longValue();
										long weekTime = 604800000L;
										long monthTime = 2592000000L;
										if (time < 0L) {
											num = Integer.valueOf(-1);
										} else {
											writeLic = (String) serialNumberList.get(i);
											if (time <= weekTime) {
												num = Integer.valueOf(0);
											} else if (time <= monthTime) {
												num = Integer.valueOf(1);
											} else
												num = Integer.valueOf(2);
										}
									} catch (ParseException e) {
										System.out.println("日期格式转换异常");
									}
								} else {
									System.out.println("机器码与本地不匹配");
								}
							} else
								System.out.println("序列号日期或机器码缺失");
						} else {
							System.out.println("序列号参数缺失");
						}
					} else {
						System.out.println("序列号为空");
					}
				}
			else {
				System.out.println("序列号为空");
			}

			long now = new Date().getTime();
			if (num.intValue() >= 0)
				if ((hisoryTime != null) && (hisoryFlag != null)) {
					if (now > hisoryTime.longValue())
						writeToFile(new StringBuilder().append(now).append("#pass#").append(writeLic).toString());
					else
						num = Integer.valueOf(-1);
				} else
					writeToFile(new StringBuilder().append(now).append("#pass#").append(writeLic).toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return num;
	}

	public static String getDeSerialNumber(List<String> serialNumberList) {
		Integer num = Integer.valueOf(-2);

		Long hisoryTime = null;
		String hisoryFlag = null;
		String writeLic = "";
		try {
			List historyList = readToFile();
			if ((historyList != null) && (historyList.size() > 0)) {
				String hisory = (String) historyList.get(historyList.size() - 1);
				String[] hisorys = hisory.split("#");
				hisoryTime = Long.valueOf(hisorys.length > 0 ? hisorys[0] : "");
				hisoryFlag = hisorys.length > 1 ? hisorys[1] : "";
			}

			if ((serialNumberList != null) && (serialNumberList.size() > 0))
				for (int i = 0; i < serialNumberList.size(); i++) {
					String serialNumber = (String) serialNumberList.get(i);
					if ((serialNumber != null) && (serialNumber != "") && (serialNumber.length() > 0)) {
						String enSerialNumber = serialNumber;
						for (int j = 0; j < enNum.intValue(); j++) {
							enSerialNumber = base64Decode(enSerialNumber);
						}

						String[] serialNumbers = enSerialNumber.split("\\^");
						if (serialNumbers.length == 7) {
							String machineCode = getSerialybMachineCode();

							String serialMachineCode = serialNumbers[6];

							String serialEndTime = serialNumbers[3];
							if ((serialMachineCode != null) && (serialMachineCode.length() > 0)
									&& (serialEndTime != null) && (serialEndTime.length() > 0)) {
								if (machineCode.equals(serialMachineCode)) {
									SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
									try {
										Date date = simpleDateFormat.parse(serialEndTime);
										String currentDate = simpleDateFormat.format(new Date());
										Date currentDay = simpleDateFormat.parse(currentDate);
										Long currentMillis = Long.valueOf(currentDay.getTime());
										Long dateMillis = Long.valueOf(date.getTime());
										long time = dateMillis.longValue() - currentMillis.longValue();
										long weekTime = 604800000L;
										long monthTime = 2592000000L;
										if (time < 0L) {
											num = Integer.valueOf(-1);
										} else {
											writeLic = enSerialNumber;
											if (time <= weekTime) {
												num = Integer.valueOf(0);
											} else if (time <= monthTime) {
												num = Integer.valueOf(1);
											} else
												num = Integer.valueOf(2);
										}
									} catch (ParseException e) {
										System.out.println("日期格式转换异常");
									}
								} else {
									System.out.println("机器码与本地不匹配");
								}
							} else
								System.out.println("序列号日期或机器码缺失");
						} else {
							System.out.println("序列号参数缺失");
						}
					} else {
						System.out.println("序列号为空");
					}
				}
			else {
				System.out.println("序列号为空");
			}

			long now = new Date().getTime();
			if ((num.intValue() >= 0) && (hisoryTime != null) && (hisoryFlag != null)
					&& (now <= hisoryTime.longValue())) {
				num = Integer.valueOf(-1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if ((writeLic != null) && (writeLic.length() > 0)) {
			String status;
			if (num.intValue() >= 0)
				status = "正常";
			else {
				status = "过期";
			}
			String[] strings = writeLic.split("\\^");
			StringBuffer base64Str = new StringBuffer();
			base64Str.append(strings[0]);
			base64Str.append("^");
			base64Str.append(strings[1]);
			base64Str.append("^");
			base64Str.append(authorizationType.get(strings[2]));
			base64Str.append("^");
			base64Str.append(strings[3]);
			base64Str.append("^");
			base64Str.append(strings[4]);
			base64Str.append("^");
			if ("DV".equals(strings[2])) {
				Map authorizationPurpose = new HashMap();
				authorizationPurpose.put("4", "测试");
				authorizationPurpose.put("5", "培训");
				authorizationPurpose.put("2", "演示");
				authorizationPurpose.put("1", "开发");
				base64Str.append(authorizationPurpose.get(strings[5]));
			} else if ("BTV".equals(strings[2])) {
				Map authorizationPurpose = new HashMap();
				authorizationPurpose.put("1", "生产");
				authorizationPurpose.put("3", "开发");
				authorizationPurpose.put("4", "测试");
				authorizationPurpose.put("5", "培训");
				base64Str.append(authorizationPurpose.get(strings[5]));
			} else if ("BPV".equals(strings[2])) {
				Map authorizationPurpose = new HashMap();
				authorizationPurpose.put("1", "生产");
				authorizationPurpose.put("2", "演示");
				authorizationPurpose.put("4", "测试");
				authorizationPurpose.put("5", "培训");
				base64Str.append(authorizationPurpose.get(strings[5]));
			}
			base64Str.append("^");
			base64Str.append(status);
			base64Str.append("^");
			base64Str.append(strings[6]);
			return base64Str.toString();
		}
		return "";
	}

	public static String getCpuId() throws IOException {
		String[] linux = { "dmidecode", "-t", "processor", "|", "grep", "'ID'" };
		String[] windows = { "wmic", "cpu", "get", "ProcessorId" };

		String property = System.getProperty("os.name");
		Process process = Runtime.getRuntime().exec(property.contains("Window") ? windows : linux);
		process.getOutputStream().close();
		Scanner sc = new Scanner(process.getInputStream(), "utf-8");
		sc.next();
		return sc.next();
	}

	public static String getMacAddress() throws IOException {
		String os = System.getProperty("os.name");
		String macAddress;
		if (os.startsWith("Windows")) {
			macAddress = getWinMacAddress();
		} else {
			if (os.startsWith("Linux"))
				macAddress = getLinuxMacAddress();
			else
				throw new IOException(new StringBuilder().append("Unknow operating system:").append(os).toString());
		}
		System.err.println("mac："+macAddress);
		return macAddress;
	}

	private static String getLinuxMacAddress() {
		String mac = "";
		try {
			Process p = new ProcessBuilder(new String[] { "ifconfig" }).start();
			BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = br.readLine()) != null) {
				Pattern pat = Pattern.compile("\\b\\w+:\\w+:\\w+:\\w+:\\w+:\\w+\\b");
				Matcher mat = pat.matcher(line);
				if (mat.find()) {
					mac = mat.group(0).toLowerCase().replaceAll(":", "-");
				}
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
			String message = e.getMessage();
			if (message.contains("ifconfig"))
				mac = "-1";
			else {
				mac = "-2";
			}
		}
		System.out.println(new StringBuilder().append("本机MAC地址为:\n").append(mac).toString());
		return mac;
	}

	private static String getWinMacAddress() throws UnknownHostException, SocketException {
		InetAddress ia = InetAddress.getLocalHost();
		InetAddress[] inetAddressArr = InetAddress.getAllByName(ia.getHostName());
		for (int i = 0; i < inetAddressArr.length; i++) {
			if (inetAddressArr[i].getHostAddress() != null) {
				String ip = inetAddressArr[i].getHostAddress();
				if ((!ip.endsWith(".1")) && (!ip.endsWith(".0")) && (!ip.endsWith(".255"))) {
					ia = inetAddressArr[i];
					break;
				}
			}

		}

		byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();

		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < mac.length; i++) {
			if (i != 0) {
				sb.append("-");
			}

			String s = Integer.toHexString(mac[i] & 0xFF);
			sb.append(s.length() == 1 ? new StringBuilder().append(0).append(s).toString() : s);
		}

		return sb.toString().toUpperCase();
	}

	private static String base64Encode(String str) {
		byte[] b = null;
		String s = null;
		try {
			b = str.getBytes("utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if (b != null) {
			s = new BASE64Encoder().encode(b);
		}

		return s;
	}

	private static String base64Decode(String str) {
		byte[] b = null;
		String result = null;
		if (str != null) {
			BASE64Decoder decoder = new BASE64Decoder();
			try {
				b = decoder.decodeBuffer(str);
				result = new String(b, "utf-8");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	static {
		authorizationType.put("DV", "个人演示版");
		authorizationType.put("BTV", "企业合同版");
		authorizationType.put("BPV", "企业永久版");

		enNum = Integer.valueOf(2);
	}
}
